package org.devgframwork.datasync.core.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class CommonUtil {

  private static final Logger logger = LoggerFactory.getLogger(CommonUtil.class);
  public static final String charset = "UTF-8";
  public static final String dataSyncAll = "DATA_SYNC_ALL";  // 全量同步队列
  public static final String ID = "id";
  public static final String defaultDateFormat = "yyyy-MM-dd HH:mm:ss";
  public static final String DOT = ".";
  public static final String INSERT = "insert";
  public static final String UPDATE = "update";
  public static final String DELETE = "delete";
  public static final String CANALEVENTTYPE = "canalEventType";
  public static final String COMMA = ",";
  public static final Integer defaultTimeOut = 10000;
  public static final String suffixExchange = "_exchange";


  public static boolean eq(String name, String value) {
    if (null != name && name.equals(value)) {
      return true;
    }
    return false;
  }

  public static boolean startsWith(String name, String value) {
    if (null != name && name.startsWith(value)) {
      return true;
    }
    return false;
  }

  public static boolean indexOf(String name, String value) {
    if (null != name && name.indexOf(value) >= 0) {
      return true;
    }
    return false;
  }

  public static String getSeqValue() {
    SimpleDateFormat sdf = new SimpleDateFormat("YYYYMMddHHmmssSSS");
    Random ne = new Random();
    int x = ne.nextInt(9999 - 1000 + 1) + 1000;
    return (sdf.format(new Date()) + x);
  }

  public static String dateToStr(Date date, String format) {
    SimpleDateFormat sdf = null;
    try {
      sdf = new SimpleDateFormat(format);
    } catch (Exception ex) {
      sdf = new SimpleDateFormat("yyyyMMdd");
    }
    return sdf.format(date);
  }

  public static String dateToStrNow(String format) {
    return dateToStr(new Date(), format);
  }

  public static Date strToDate(String date, String format) {
    try {
      SimpleDateFormat sdf = new SimpleDateFormat(format);
      return sdf.parse(date);
    } catch (Exception e) {
      e.printStackTrace();
      return null;
    }
  }

  public static Date strToDate(String date) {
    return strToDate(date, defaultDateFormat);
  }


  public static Timestamp dateToTimestamp(Date date) {
    long longTime = date.getTime();
    Timestamp timestamp = new Timestamp(longTime);
    return timestamp;
  }

  public static Timestamp dateToTimestampNow() {
    return dateToTimestamp(new Date());
  }

  public static String getToken(String loginName) {
    int random = new Random().nextInt(900) + 100;
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS");
    String time = sdf.format(new Date());
    return "LoginUser:" + loginName + ":" + time + random;
  }

  public static String getMapString(Map<String, Object> map, String string) {
    return map == null ? null : map.get(string) == null ? null : String.valueOf(map.get(string));
  }

  public static String mapToString(Map map, String string) {
    return map == null ? "" : map.get(string) == null ? "" : String.valueOf(map.get(string));
  }

  public static String mapToString(Map map, String string, String defaultValue) {
    return map == null ? defaultValue : map.get(string) == null ? defaultValue : String.valueOf(map.get(string));
  }

  public static String mapToNullString(Map map, String string) {
    return map == null ? null : map.get(string) == null ? null : String.valueOf(map.get(string));
  }

  public static <T> T mapToT(Map<String, T> map, String string) {
    return map == null ? null : map.get(string) == null ? null : map.get(string);
  }

  public static BigDecimal mapToBigDecimal(Map map, String string) {
    return map == null ? BigDecimal.ZERO : map.get(string) == null ? BigDecimal.ZERO
        : new BigDecimal(String.valueOf(map.get(string)));
  }

  public static Long mapToLong(Map map, String string) {
    return map == null ? null
        : map.get(string) == null ? null : Long.valueOf(String.valueOf(map.get(string)));
  }

  public static List mapToList(Map map, String string) {
    return map == null ? null : map.get(string) == null ? null : (List) map.get(string);
  }

  public static Object mapToObject(Map map, String string) {
    return map == null ? null : map.get(string);
  }

  public static String[] mapToStringArray(Map map, String string) {
    return map == null ? null : map.get(string) == null ? null : (String[]) map.get(string);
  }

  public static Date mapToDate(Map map, String string) {
    return map == null ? null : map.get(string) == null ? null : (Date) map.get(string);
  }

  public static Map mapToMap(Map map, String string) {
    return map == null ? null : map.get(string) == null ? null : (Map) map.get(string);
  }

  public static boolean isEmpty(String str) {
    return str == null || str.equals("");
  }

  public static boolean isTrimEmpty(String str) {
    return str == null || str.trim().equals("");
  }

  public static boolean isEmpty(String[] strArray) {
    return strArray == null || strArray.length <= 0;
  }

  public static boolean isEmpty(List list) {
    return list == null || list.size() <= 0;
  }

  public static boolean isEmpty(Object object) {
    return object == null;
  }

  public static boolean isNullOrEmpty(String str) {
    if (null == str || str.trim().equals("")) {
      return true;
    }
    return false;
  }

  public static Map<String, Object> objectToMap(Object obj) {
    if (obj == null) {
      return null;
    }
    return (Map<String, Object>) obj;
  }

  /**
   * 利用正则表达式判断字符串是否是数字
   */
  public static boolean isNumeric(String str) {
    Pattern pattern = Pattern.compile("[0-9]*");
    Matcher isNum = pattern.matcher(str);
    if (!isNum.matches()) {
      return false;
    }
    return true;
  }


  public static String getCookieValue(HttpServletRequest request, String cookieName) {
    // TODO Auto-generated method stub
    String cookieValue = null;
    Cookie[] cookies = request.getCookies(); // 这样便可以获取一个cookie数组
    if (null != cookies && cookies.length > 0) {
      for (Cookie cookie : cookies) {
        String coolieName = cookie.getName();
        if (null != coolieName && coolieName.equals(cookieName)) { // cookie存在登录成功
          cookieValue = cookie.getValue();
          break;
        }
      }
    }
    return cookieValue;
  }

  public static void setCookieValue(
      HttpServletResponse response, String name, String value, int maxAge) {
    // TODO Auto-generated method stub
    setCookieValue(response, name, value, maxAge, true);
  }

  public static void setCookieValue(
      HttpServletResponse response, String name, String value, int maxAge, boolean httpOnly) {
    // TODO Auto-generated method stub
    Cookie cookie = new Cookie(name, value); // 设置cookie和redis超时时间
    cookie.setMaxAge(maxAge); //单位秒
    cookie.setPath("/");
    if (httpOnly) {
      cookie.setHttpOnly(true);
    }
    response.addCookie(cookie);
  }

  //private static double EARTH_RADIUS = 6378.137;
  private static double EARTH_RADIUS = 6371.393;

  private static double rad(double d) {
    return d * Math.PI / 180.0;
  }

  /**
   * 计算两个经纬度之间的距离
   *
   * @param lat1
   * @param lng1
   * @param lat2
   * @param lng2
   * @return
   */
  public static double getDistance(double lat1, double lng1, double lat2, double lng2) {
    double radLat1 = rad(lat1);
    double radLat2 = rad(lat2);
    double a = radLat1 - radLat2;
    double b = rad(lng1) - rad(lng2);
    double s = 2 * Math.asin(Math.sqrt(Math.abs(Math.pow(Math.sin(a / 2), 2) +
        Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))));
    s = s * EARTH_RADIUS;
//    s = Math.round(s * 1000);
    return s;
  }

  public static String transferLongToDate(String dateFormat, Long millSec) {
    SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
    Date date = new Date(millSec);
    return sdf.format(date);
  }

  public static String localDateFormat(LocalDate localDate, String pattern) {
    return localDate.format(DateTimeFormatter.ofPattern(pattern));
  }

  public static void createFile(Map<String, Object> param) {
    FileWriter fileWriter = null;
    try {
      String id = CommonUtil.mapToString(param, "id");
      String content = CommonUtil.mapToString(param, "content", "");
      String path = CommonUtil.mapToString(param, "path");
      if (null == id || id.equals("")) {
        logger.error("createFile error", "id can not be null");
        return;
      }
      if (null == path || path.equals("")) {
        logger.error("createFile error", "path can not be null");
        return;
      }
      File fileDir = new File(path);
      // 没有文件夹时新建文件夹
      if (!fileDir.exists()) {
        fileDir.mkdirs();
      }
      String filePath = path + id + ".txt";
      File file = new File(filePath);
      if (file.exists()) {
        file.delete();
      }
      file.createNewFile();
      //创建文本文件
      fileWriter = new FileWriter(file);
      fileWriter.write(content);
      fileWriter.flush();
    } catch (Exception e) {
      // TODO Auto-generated catch block
      logger.error("create file error", e);
    } finally {
      if (fileWriter != null) {
        try {
          fileWriter.close();
        } catch (IOException ex) {
          logger.error("close fileWriter error", ex);
        }
      }
    }
  }

  public static void main(String args[]) {
    String time = transferLongToDate("yyyy-MM-dd HH:mm:ss", 1569404844000L);
    System.out.println(time);
//    System.out.println(getDistance(30.530102, 114.316164, 30.529670, 114.332020));
  }

}
